package demoMod.anm2editor.ui;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import demoMod.anm2editor.fonts.FontKeys;
import demoMod.anm2editor.interfaces.ReloadStringsSubscriber;
import demoMod.anm2editor.localization.LocalizedStrings;
import demoMod.anm2editor.model.Animation;
import demoMod.anm2editor.model.Event;
import demoMod.anm2editor.model.Operation;
import demoMod.anm2editor.model.Project;
import demoMod.anm2editor.utils.IdGenerator;
import demoMod.gdxform.abstracts.Container;
import demoMod.gdxform.core.FormManager;
import demoMod.gdxform.helpers.FontHelper;
import demoMod.gdxform.interfaces.Element;
import demoMod.gdxform.interfaces.MouseEventSubscriber;
import demoMod.gdxform.ui.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EventPane extends Container<Element> implements MouseEventSubscriber, ReloadStringsSubscriber {
    public static final String ID = "EventPane";
    private final EventList eventList = new EventList();
    private final GScrollPane scrollPane;
    private boolean mouseDown = false;
    private final GLabel label;

    public EventPane() {
        setWidth(Gdx.graphics.getWidth() * 0.1F);
        setHeight(Gdx.graphics.getHeight() * 0.2F);
        setX(0.8F * Gdx.graphics.getWidth());
        setY(20);
        setBackground(Color.WHITE.cpy());
        setBackground(Color.GRAY.cpy());
        setId(ID);
        scrollPane = new GScrollPane(0, 20, getWidth(), getHeight() - 40.0F, getWidth() * 2, getHeight() * 2);
        scrollPane.setBackground(Color.WHITE.cpy());
        scrollPane.setBackground(Color.DARK_GRAY.cpy());
        GVScrollBar vScrollBar = new GVScrollBar(0, 0, 10, getHeight());
        scrollPane.setVScrollBar(vScrollBar);
        addElement(scrollPane);
        eventList.setCellHeight(((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight());
        eventList.setMaxSelectedItems(1);
        scrollPane.addElement(eventList);
        setBorderWidth(1);
        setBorder(Color.LIGHT_GRAY.cpy());
        label = new GLabel(5.0F, getHeight() - 10.0F, getWidth(), 20.0F, FontHelper.getFont(FontKeys.SIM_HEI_16));
        List<String> strings = LocalizedStrings.getStrings(ID);
        label.setText(strings.get(3));
        addElement(label);
        LocalizedStrings.subscribe(this);
    }

    public GScrollPane getScrollPane() {
        return scrollPane;
    }

    public EventList getEventList() {
        return eventList;
    }

    public void addEvent(Event event) {
        EventItem eventItem = new EventItem(getWidth(), ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight(), event, FontHelper.getFont(FontKeys.SIM_HEI_14));
        eventList.addItem(eventItem);
        eventItem.setId(Integer.toString(event.getId()));
    }

    public void addEvent(int index, Event event) {
        EventItem eventItem = new EventItem(getWidth(), ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight(), event, FontHelper.getFont(FontKeys.SIM_HEI_14));
        eventList.addItem(index, eventItem);
        eventItem.setId(Integer.toString(event.getId()));
    }

    public void removeEvent(EventItem eventItem) {
        eventList.removeItem(eventItem);
    }

    public void clear() {
        for (Element element : eventList.getElements()) {
            element.dispose();
        }
        eventList.clear();
        scrollPane.getVScrollBar().setProgress(0);
    }

    @Override
    public boolean clickDown(int screenX, int screenY, int button) {
        if (screenX > getX(true) && screenX < getX(true) + getWidth() && Gdx.graphics.getHeight() - screenY > getY(true)
                && Gdx.graphics.getHeight() - screenY < getY(true) + getHeight()) {
            mouseDown = true;
            FormManager.getInstance().moveToTop(this);
            List<Element> elements = this.getElements();
            for(int i = elements.size() - 1; i >= 0; --i) {
                Element element = elements.get(i);
                if (element instanceof MouseEventSubscriber && ((MouseEventSubscriber)element).clickDown(screenX, screenY, button)) {
                    return true;
                }
            }
            if (button == Input.Buttons.RIGHT) {
                GMenuList menuList = new GMenuList();
                menuList.setWidth(150.0F);
                menuList.setX(screenX);
                menuList.setY(Gdx.graphics.getHeight() - screenY);
                List<String> strings = LocalizedStrings.getStrings(ID);
                GMenuItem newEvent = new GMenuItem(menuList.getWidth(), menuList.getMenuItemHeight(), strings.get(0) + "...", FontHelper.getFont(FontKeys.SIM_HEI_14)) {
                    @Override
                    public void onClick() {
                        TextInputWindow textInputWindow = new TextInputWindow(strings.get(1), "", FontHelper.getFont(FontKeys.SIM_HEI_14));
                        textInputWindow.setConfirmCallback(name -> {
                            Event event = new Event();
                            event.setId(IdGenerator.nextEventId());
                            event.setName(name);
                            Map<String, List<Integer>> usages = new HashMap<>();
                            for (Animation animation : Project.currentProject.getAnimations()) {
                                usages.put(animation.getName(), new ArrayList<>());
                            }
                            event.setUsages(usages);
                            Project.currentProject.getEvents().add(event);
                            EventItem eventItem = new EventItem(getWidth(), ((Timeline) FormManager.getInstance().getContainerById(Timeline.ID)).getTrackHeight(), event, FontHelper.getFont(FontKeys.SIM_HEI_14));
                            eventList.addItem(eventItem);
                            eventItem.setId(Integer.toString(event.getId()));
                            if (Project.currentProject.getEvents().size() * eventList.getCellHeight() > scrollPane.getPlainHeight()) {
                                scrollPane.setPlainHeight(scrollPane.getPlainHeight() + eventList.getCellHeight());
                            }
                            Operation operation = new Operation() {
                                @Override
                                public void undo() {
                                    Project.currentProject.getEvents().remove(event);
                                    removeEvent(eventItem);
                                    if (Project.currentProject.getEvents().size() * eventList.getCellHeight() < scrollPane.getPlainHeight()
                                            && scrollPane.getPlainHeight() - eventList.getCellHeight() > scrollPane.getHeight()) {
                                        scrollPane.setPlainHeight(scrollPane.getPlainHeight() - eventList.getCellHeight());
                                    }
                                }

                                @Override
                                public void redo() {
                                    Project.currentProject.getEvents().add(event);
                                    eventList.addItem(eventItem);
                                    if (Project.currentProject.getEvents().size() * eventList.getCellHeight() > scrollPane.getPlainHeight()) {
                                        scrollPane.setPlainHeight(scrollPane.getPlainHeight() + eventList.getCellHeight());
                                    }
                                }
                            };
                            operation.setName(strings.get(2));
                            ((HistoryPanel) FormManager.getInstance().getContainerById(HistoryPanel.ID)).addOperation(operation);
                        });
                    }
                };
                newEvent.setSplitLine(false);
                menuList.addElement(newEvent);
                FormManager.getInstance().addContainer(menuList);
                FormManager.getInstance().moveToTop(menuList);
            }
            FormManager.getInstance().getEventHooks().setCurrentFocusedElement(this);
            return true;
        }
        return false;
    }

    @Override
    public boolean clickUp(int screenX, int screenY, int button) {
        if (!this.mouseDown) return false;
        this.mouseDown = false;
        List<Element> elements = this.getElements();

        for(int i = elements.size() - 1; i >= 0; --i) {
            Element element = elements.get(i);
            if (element instanceof MouseEventSubscriber && ((MouseEventSubscriber)element).clickUp(screenX, screenY, button)) {
                break;
            }
        }
        return true;
    }

    @Override
    public boolean mouseDragged(int screenX, int screenY) {
        List<Element> elements = getElements();
        for (int i=elements.size() - 1;i >= 0;i--) {
            Element element = elements.get(i);
            if (element instanceof MouseEventSubscriber) {
                if (((MouseEventSubscriber) element).mouseDragged(screenX, screenY)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean mouseMoved(int screenX, int screenY) {
        return false;
    }

    @Override
    public boolean scrolled(int amount) {
        if (!this.visible()) return false;
        List<Element> elements = getElements();
        for (int i=elements.size() - 1;i >= 0;i--) {
            Element element = elements.get(i);
            if (element instanceof MouseEventSubscriber) {
                if (((MouseEventSubscriber) element).scrolled(amount)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean moveToElementBorder(Element element) {
        return false;
    }

    @Override
    public boolean hasFocus() {
        return true;
    }

    @Override
    public void onReloadStrings() {
        List<String> strings = LocalizedStrings.getStrings(ID);
        label.setText(strings.get(3));
    }
}
